﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Wicture.EPC.Service.Benz.Models;

namespace Wicture.EPC.Service.Benz.Filters
{
    public class VinFilter
    {
        public static void FilterResult(Query_PartsResult item, ISet<string> featureCodes,Dictionary<string,List<FootNote>> footNotes, string chassis, dynamic vinInfo)
        {
            item.belongToVin = true;
            FilterSteering(item);
            FilterBCode(item, featureCodes);
            FilterFootNotes(item, footNotes, chassis, vinInfo, featureCodes);
        }

        public static List<string> GetFintnumList(string footNotes)
        {
            if (footNotes == null) return new List<string>();
            int index = 0;
            List<string> retList = new List<string>();
            while (index * 3 < footNotes.Length)
            {
                string fintnum = footNotes.Substring(index * 3, 3);
                index++;
                if (fintnum.Length < 3)
                {
                    break;
                }
                retList.Add(fintnum);
            }
            return retList;
        }

        private static void FilterFootNotes(Query_PartsResult item, Dictionary<string, List<FootNote>> footNotes, string chassis, dynamic vinInfo, ISet<string> featureCodes)
        {
            if (!item.belongToVin)
            {
                return;
            }
            if (string.IsNullOrEmpty(item.footNotes))
            {
                return;
            }
            var fintnumList = GetFintnumList(item.footNotes);
            var normalFitNums = fintnumList.Where(q => !q.StartsWith('9')).ToList();
            bool normalResult = GetNormalFootNotesResult(normalFitNums, footNotes, chassis, vinInfo);
            if(!normalResult)
            {
                item.belongToVin = false;
                return;
            }
            var colorFitNums = fintnumList.Where(q => q.StartsWith('9')).ToList();
            if(!colorFitNums.Any())
            {
                return;
            }
            string colorDesc = "";
            var colorCode = GetColorFootNotesResult(colorFitNums, footNotes, chassis, vinInfo, featureCodes, out colorDesc);
            if(string.IsNullOrEmpty(colorCode))
            {
                item.belongToVin = false;
                return;
            }
            item.partCode += colorCode;
            item.colorCode = colorCode;
            if(!string.IsNullOrEmpty(colorDesc))
            {
                item.nameZh += $"({colorDesc})";
            }
        }

        private static string GetColorFootNotesResult(List<string> fituums, Dictionary<string, List<FootNote>> footNotes, string chassis, dynamic vinInfo, ISet<string> featureCodes, out string colorDesc)
        {
            colorDesc = "";
            //彩色脚注：49417	N	400000	0	F	9F81  097004         VU3/VX3/VU5/VX1/VH6/VH7     
            foreach (var fintnum in fituums)
            {
                if (!footNotes.ContainsKey(fintnum))
                {
                    continue;
                }
                var colorNotes = footNotes[fintnum].Where(q => q.Lang == "N");
                foreach (var colorNote in colorNotes)
                {
                    string colorCode = colorNote.Text.Substring(0, 4);
                    string colorFootNoteStr = colorNote.Text.Substring(4, 17).Trim();
                    string colorBCodes = colorNote.Text.Substring(21).Trim();
                    BCodeEx ex = new BCodeEx(colorBCodes);
                    bool isMathColorBCodes = ex.IsMatch(featureCodes);
                    if (!isMathColorBCodes)
                    {
                        continue;
                    }
                    var fintnumList = GetFintnumList(colorFootNoteStr);
                    bool footNotesRes = GetNormalFootNotesResult(fintnumList, footNotes, chassis, vinInfo);
                    if (!footNotesRes)
                    {
                        continue;
                    }
                    colorDesc = footNotes[fintnum].FirstOrDefault(q => q.Lang == "Z" && q.SeqNum > colorNote.SeqNum)?.Text?.Trim();
                    return colorCode;
                }
            }
            return "";
        }

        private static bool GetNormalFootNotesResult(List<string> fituums, Dictionary<string, List<FootNote>> footNotes, string chassis, dynamic vinInfo)
        {
            if(fituums == null || fituums.Count == 0)
            {
                return true;
            }
            List<NameValue> abbrResList = new List<NameValue>();
            foreach(var fintnum in fituums)
            {
                if(!footNotes.ContainsKey(fintnum))
                {
                    continue;
                }
                FootNote footNote = footNotes[fintnum].FirstOrDefault(x => x.Lang != "Z");
                if (footNote == null || string.IsNullOrEmpty(footNote.Abbr) || !_Abbrs.Contains(footNote.Abbr) || string.IsNullOrEmpty(footNote.Text))
                {
                    continue;
                }
                bool footNoteFilter = FilterFootNote(footNote, chassis, vinInfo);
                abbrResList.Add(new NameValue { Name = footNote.Abbr, Value = footNoteFilter });
            }
            var groups = abbrResList.GroupBy(q => q.Name);
            foreach (var group in groups)
            {
                if (group.All(q => !q.Value))
                {
                    return false;
                }
            }
            return true;
        }

        private class NameValue
        {
            public string Name { set; get; }
            public bool Value { set; get; }
        }

        private static readonly string[] _Abbrs = new string[] { "EBF", "EAF", "EAM", "EBM", "EAG", "EBG" };

        private static bool FilterFootNote(FootNote footNote, string chassis, dynamic vinInfo)
        {
            var engineCode = vinInfo.engine.Replace(" ","");
            var transCode = vinInfo.transmission.Replace(" ", "");
            var engTransCode = GetEngTransCodeFromFootNote(footNote.Text);
            var chassCode = GetChassCodeFormFootNote(footNote.Text);
            string date = vinInfo.releaseDate;
            if (string.IsNullOrEmpty(date))
            {
                date = vinInfo.deliveryDate;
            }
            var dateFootNote = getDateFromFootNote(footNote.Text);
            switch (footNote.Abbr)
            {
                case "EBF":
                    if (!string.IsNullOrEmpty(chassCode) && CompareChassEngTransCode(chassis, chassCode) > 0)
                    {
                        return false;
                    }
                    if (CompareDate(date, dateFootNote) > 0)
                    {
                        return false;
                    }
                    break;
                case "EAF":
                    if (!string.IsNullOrEmpty(chassCode) && CompareChassEngTransCode(chassis, chassCode) < 0)
                    { 
                        return false;
                    }
                    if (CompareDate(date, dateFootNote) < 0)
                    {
                        return false;
                    }
                    break;
                case "EAM": 
                    if (!string.IsNullOrEmpty(engTransCode) && CompareChassEngTransCode(engineCode, engTransCode) < 0)
                    {
                        return false;
                    }
                    if (CompareDate(date, dateFootNote) < 0)
                    {
                        return false;
                    }
                    break;
                case "EBM":
                    if (!string.IsNullOrEmpty(engTransCode) && CompareChassEngTransCode(engineCode, engTransCode) > 0)
                    {
                        return false;
                    }
                    if (CompareDate(date, dateFootNote) > 0)
                    {
                        return false;
                    }
                    break;
                case "EAG":
                    if (!string.IsNullOrEmpty(engTransCode) && CompareChassEngTransCode(transCode, engTransCode) < 0)
                    {
                        return false;
                    }
                    if (CompareDate(date, dateFootNote) < 0)
                    {
                        return false;
                    }
                    break;
                case "EBG":
                    if (!string.IsNullOrEmpty(engTransCode) && CompareChassEngTransCode(transCode, engTransCode) > 0)
                    {
                        return false;
                    }
                    if (CompareDate(date, dateFootNote) > 0)
                    {
                        return false;
                    }
                    break;

            }
            return true;
        }

        private static string GetChassCodeFormFootNote(string text)
        {
            try
            {
                return text.Substring(2, 6).Trim(); ;
            }
            catch
            {
                return "";
            }
        }

        private static int CompareDate(string date, string date2)
        {
            int a = date.ToInt();
            if (a < 500000)
            {
                a += 20000000;
            }
            else
            {
                a += 19000000;
            }
            int b = date2.ToInt();
            if (a == b)
            {
                return 0;
            }
            else if (a > b)
            {
                return 1;
            }
            else
            {
                return -1;
            }
        }

        private static int CompareChassEngTransCode(string engineCode, string engineCode2)
        {
            if (string.IsNullOrEmpty(engineCode))
            {
                return 0;
            }
            if (engineCode2.Length == 1)
            {
                engineCode = engineCode.Substring(engineCode.Length - 8, 1);
            }
            else
            {
                engineCode = engineCode.Substring(engineCode.Length - engineCode2.Length, engineCode2.Length);
            }

            for (int i = 0; i < engineCode.Length; i++)
            {
                var a = engineCode[i];
                var b = engineCode2[i];
                if (a > b)
                {
                    return 1;
                }
                else if (a < b)
                {
                    return -1;
                }
            }

            return 0;
        }

        private static string GetEngTransCodeFromFootNote(string text)
        {
            try
            {
                return text.Substring(0, 8).Trim();
            }
            catch
            {
                return "";
            }
        }

        private static string getDateFromFootNote(string text)
        {
            try
            {
                return text.Substring(8, 8).Trim(); ;
            }
            catch
            {
                return "";
            }
        }

        private static void FilterBCode(Query_PartsResult item, ISet<string> featureCodes)
        {
            if (!item.belongToVin)
            {
                return;
            }
            if (!string.IsNullOrEmpty(item.codeB))
            {
                BCodeEx ex = new BCodeEx(item.codeB);
                item.belongToVin = ex.IsMatch(featureCodes);
                item.saCodeCount = ex.SaCodeCount;
            }
        }

        private static void FilterSteering(Query_PartsResult item)
        {
            if (!item.belongToVin)
            {
                return;
            }
            //中国市场转向机都是L,剔除R的
            if (item.steering == "  XX" || item.steering == "  X " || item.steering == "   X")
            {
                item.belongToVin = false;
            }
        }

        private static void GetCodeBArray(List<string> adds, List<string> minus, string groupCodes)
        {
            string addStr = groupCodes;
            List<int> indexs = new List<int>();
            char[] chars = groupCodes.ToCharArray();
            for (int i = 0; i < chars.Length; i++)
            {
                if (chars[i].ToString() == "-") indexs.Add(i);
            }
            for (int i = 0; i < indexs.Count(); i++)
            {
                var minu = groupCodes.Substring(indexs[i] + 1, 3);
                minus.Add(minu);
                addStr = addStr.Replace("-" + minu, "");
            }
            addStr = addStr.Replace("+", "");
            for (int j = 0; j < addStr.Length; j += 3)
            {
                adds.Add(addStr.Substring(j, 3));
            }
        }
    }
}
